import * as THREE from "three";
import { OrbitControls } from "three/addons/controls/OrbitControls.js";
import { TransformControls } from 'three/addons/controls/TransformControls.js';
import { DragControls } from 'three/addons/controls/DragControls.js'

import { indices, uvs, groups } from './attr.js'

let scene,
    camera,
    renderer,
    planeMesh,
    gridHelper,
    wpWidth,
    wpHeight,
    orbitControls,
    dragControls,
    transControls;

let activeMesh = null;  // 当前活动的构件
let activeFace = null;  // 编辑的面
let isEditFW = false; // 是否正在编辑模板

let draged = false;

// 创建 Raycaster 和鼠标 Vector2
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();

let lastMousePosition = new THREE.Vector3();  // 记录鼠标按下时候的位置

export function initScene(anchor) {
    anchor = anchor || 'body'
    // 创建场景
    scene = new THREE.Scene();
    scene.background = new THREE.Color(0x000000);

    const container = document.querySelector(anchor);

    wpWidth = container.offsetWidth;
    wpHeight = container.offsetHeight;
    // 创建相机
    camera = new THREE.PerspectiveCamera(90, wpWidth / wpHeight, 0.1, 1000000);
    // camera.position.x = -300;
    // camera.position.y = -300;
    camera.position.z = 900;

    // 创建渲染器
    renderer = new THREE.WebGLRenderer({ antialias: true });
    // 渲染器能够渲染阴影效果
    renderer.shadowMap.enabled = true;
    renderer.setSize(wpWidth, wpHeight);
    container.appendChild(renderer.domElement);

    // 创建一个平面作为底板
    const planeGeometry = new THREE.PlaneGeometry(500000, 500000);
    const planeMaterial = new THREE.MeshStandardMaterial({
        color: 0xffffffff,
        side: THREE.DoubleSide,
        transparent: true,
        opacity: 0,
    });
    planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
    planeMesh.rotation.z = 0.5 * Math.PI;
    planeMesh.position.set(0, 0, 0);
    scene.add(planeMesh);

    // 添加网格辅助器
    gridHelper = new THREE.GridHelper(5000, 100); // 创建一个200单位的网格，细分为50个方格
    gridHelper.rotation.x = 0.5 * Math.PI;
    //gridHelper.position.y = -150;
    scene.add(gridHelper);

    // 方向光
    const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
    directionalLight.position.set(10, 10, 10);

    directionalLight.shadow.mapSize.width = 1024; // default
    directionalLight.shadow.mapSize.height = 1024; // default
    directionalLight.shadow.camera.near = 0.05; // default
    directionalLight.shadow.camera.far = 500; // default
    //将范围调大
    directionalLight.shadow.camera.top = 20; /// 这个是生效的属性
    directionalLight.shadow.camera.right = 20;
    directionalLight.shadow.camera.left = -20;
    directionalLight.shadow.camera.bottom = -20;
    directionalLight.castShadow = true;
    scene.add(directionalLight);

    // 环境光
    const ambientLight = new THREE.AmbientLight(0xffffff, 2);
    scene.add(ambientLight);

    // 添加鼠标控制
    orbitControls = new OrbitControls(camera, renderer.domElement);
    // controls.enableDamping = true; // 使得相机移动更加平滑
    orbitControls.dampingFactor = 0.05; // 阻尼效果

    transControls = new TransformControls(camera, renderer.domElement)

    render()
    return { scene, camera, renderer }
}

export const addCube = (cubeOpt, hCubes, hCamera, hScene) => {
    //相机不能为空
    if (null == hCamera || typeof (hCamera) == 'undefined') {
        return null
    }
    //场景不能为空
    if (null == hScene || typeof (hScene) == 'undefined') {
        return null
    }
    //长方体数据
    var data = cubeOpt.data;
    if (null == data || typeof (data) == 'undefined') {
        cubeOpt.data = {}
        data = cubeOpt.data;
    }
    //长方体坐标转换
    var desc = data.name
    //长方体坐标点数不少于8个，多余8个只取前面8个
    var points = cubeOpt.points;
    if (null == points || typeof (points) == 'undefined' || !(points instanceof Array)) {
        console.log('创建长方体[', desc, ']没有指定顶点')
        return
    }
    var iPointSize = points.length
    if (iPointSize != 4 && iPointSize != 8) {
        console.log('创建长方体[', desc, ']顶点数量不为4个或者8个')
        return
    }
    if (iPointSize == 4) {
        pointsFrom4To8(points, data)
    }
    createCubeGeometry(points, hCubes);

    // 监听 drag 事件，限制物体只能在 XY 平面上移动
    dragControls.addEventListener('drag', function (event) {
        //event.object.position.z = 0;  // 将 Z 坐标固定为 0，确保只在 XY 平面移动
    });

    // 禁用 OrbitControls 在拖动过程中
    dragControls.addEventListener('dragstart', function () {
        if (null == orbitControls || typeof (orbitControls) == "undefined") {
            return
        }
        orbitControls.enabled = false;  // 禁用 OrbitControls
    });

    // 重新启用 OrbitControls 在拖动结束后
    dragControls.addEventListener('dragend', function () {
        if (null == orbitControls || typeof (orbitControls) == "undefined") {
            return
        }
        orbitControls.enabled = true;  // 启用 OrbitControls
    });


    //创建长方体
    function createCubeGeometry(points, hCubes) {
        //取得长方体颜色
        var data = cubeOpt.data
        var pColor = null
        if (null != data && typeof (data) != 'undefined' && (data instanceof Object)) {
            pColor = data.color;
        }
        if (null == pColor || typeof (pColor) == 'undefined' || pColor == '') {
            pColor = 0xff00ff;
        }
        var material = new THREE.MeshPhongMaterial({ color: pColor, side: THREE.DoubleSide });
        var materials = [material, material, material, material, material, material]
        var data = cubeOpt.data;
        if (null == data) {
            data = {}
        }
        var hGeometry = new THREE.BufferGeometry();
        var vertices = getCubeFacesVertices(points, desc);
        hGeometry.setAttribute("position", new THREE.BufferAttribute(new Float32Array(vertices), 3));
        hGeometry.setIndex(indices);
        hGeometry.setAttribute('uv', new THREE.BufferAttribute(uvs, 2))
        hGeometry.computeVertexNormals()
        var hMesh = new THREE.Mesh(hGeometry, materials);
        hGeometry.groups = groups
        hMesh.userData = { data: data, points: points }
        if (hCubes instanceof Array) {
            hCubes.push(hMesh)
        }
        hScene.add(hMesh);
    }
    // 将长方体的立方体的8个顶点转变为长方体的面的顶点
    function getCubeFacesVertices(points, desc) {
        if (null == points || typeof (points) == 'undefined' || !(points instanceof Array)) {
            return null
        }
        if (null == desc || typeof (desc) == 'undefined') {
            desc = ''
        }
        var iSize = points.length
        if (iSize < 8) {
            return null
        }
        var iIdx
        var point
        for (iIdx = 0; iIdx < 8; iIdx++) {
            point = points[iIdx]
            if (null == point) {
                console.log(desc, '长方体顶点存在有空值点')
                return null
            }
            //检查是否存在坐标非法点
        }
        // 每个面的顶点（顺时针或逆时针）
        const faces = [
            [0, 1, 2, 3],// 底面            
            [4, 5, 6, 7],// 顶面            
            [0, 1, 5, 4],// 前面            
            [2, 3, 7, 6],// 后面            
            [0, 3, 7, 4],// 左面            
            [1, 2, 6, 5] // 右面
        ];
        // 生成顶点数组
        const facesVertices = [];
        faces.forEach(face => {
            face.forEach(index => {
                point = points[index]
                facesVertices.push(point.x);
                facesVertices.push(point.y);
                facesVertices.push(point.z);
            });
        });
        return facesVertices;
    }

    //由平面4个点转变为8个点
    function pointsFrom4To8(points, data) {
        var type = data.type
        var z1;
        for (var i = 0; i < 4; i++) {
            var point = points[i]
            if (null == point || typeof (point) == 'undefined') {
                continue
            }
            var x = point.x
            var y = point.y
            var z = point.z
            if (!isNUmber(z)) {
                z = 0
            }

            z1 = z + 380
            if (type == 'L') {
                z1 = z + 380
                z = z + 320
            } else if (type == 'DB') {
                z1 = z + 360
                z = z + 380
            }
            point.z = z
            points.push({ x: x, y: y, z: z1 })
        }
    }
    //判别是否为数字
    function isNUmber(num) {
        if (num == null || typeof (num) == 'undefined') {
            return false
        }
        return /^[0-9]+.?[0-9]*$/.test(num);
    }
}

// 渲染场景
export const render = () => {
    orbitControls.update(); // 更新 OrbitControls
    renderer.render(scene, camera);
    requestAnimationFrame(render); // 渲染循环
};

